package com.lemon.exam.common.redis.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.data.domain.Range;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * Redis ZSet操作 类对象
 *
 * @author Lemon
 * @since 2025/7/4 18:09
 */
public final class ZSetOperations extends BaseOperations {
    public ZSetOperations(ObjectMapper objectMapper, ReactiveRedisTemplate<String, Object> template) {
        super(objectMapper, template);
    }

    /**
     * 添加元素
     *
     * @param key   键
     * @param value 值
     * @param score 分数
     * @return 是否成功
     */
    public Mono<Boolean> add(String key, Object value, double score) {
        return withRetry(
                template.opsForZSet().add(key, value, score),
                "redis zset add key: %s".formatted(key)
        ).onErrorResume(err -> Mono.just(false));
    }

    /**
     * 获取元素
     *
     * @param key   键
     * @param start 开始位置
     * @param end   结束位置
     * @param clazz 类
     * @return 元素
     */
    public <T> Flux<T> range(String key, long start, long end, Class<T> clazz) {
        return withRetry(
                template.opsForZSet().range(key, Range.open(start, end)).map(toGeneric(clazz)),
                "redis zset range key: %s".formatted(key)
        ).onErrorResume(err -> Flux.empty());
    }

    /**
     * 删除元素
     *
     * @param key   键
     * @param values 值
     * @return 是否成功
     */
    public Mono<Boolean> del(String key, Object... values) {
        return withRetry(
                template.opsForZSet().remove(key, values).map(v -> v != null && v == values.length),
                "redis zset del key: %s".formatted(key)
        ).onErrorResume(err -> Mono.just(false));
    }
}
